home *** CD-ROM | disk | FTP | other *** search
/ MacHack 2000 / MacHack 2000.toast / pc / The Hacks / MacHacksBug / Python 1.5.2c1 / Tools / idle / FormatParagraph.py < prev    next >
Encoding:
Python Source  |  2000-06-23  |  3.3 KB  |  106 lines

  1. # Extension to format a paragraph
  2.  
  3. import string
  4. import re
  5.  
  6. class FormatParagraph:
  7.  
  8.     menudefs = [
  9.         ('edit', [
  10.             ('Format Paragraph', '<<format-paragraph>>'),
  11.          ])
  12.     ]
  13.  
  14.     keydefs = {
  15.         '<<format-paragraph>>': ['<Alt-q>'],
  16.     }
  17.     
  18.     unix_keydefs = {
  19.         '<<format-paragraph>>': ['<Meta-q>'],
  20.     } 
  21.  
  22.     def __init__(self, editwin):
  23.         self.editwin = editwin
  24.  
  25.     def format_paragraph_event(self, event):
  26.         text = self.editwin.text
  27.         try:
  28.             first = text.index("sel.first")
  29.             last = text.index("sel.last")
  30.         except TclError:
  31.             first = last = None
  32.         if first and last:
  33.             data = text.get(first, last)
  34.         else:
  35.             first, last, data = find_paragraph(text, text.index("insert"))
  36.         newdata = reformat_paragraph(data)
  37.         text.tag_remove("sel", "1.0", "end")
  38.         if newdata != data:
  39.             text.mark_set("insert", first)
  40.             text.delete(first, last)
  41.             text.insert(first, newdata)
  42.         else:
  43.             text.mark_set("insert", last)
  44.         text.see("insert")
  45.  
  46. def find_paragraph(text, mark):
  47.     lineno, col = map(int, string.split(mark, "."))
  48.     line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
  49.     while text.compare("%d.0" % lineno, "<", "end") and is_all_white(line):
  50.         lineno = lineno + 1
  51.         line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
  52.     first_lineno = lineno
  53.     while not is_all_white(line):
  54.         lineno = lineno + 1
  55.         line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
  56.     last = "%d.0" % lineno
  57.     # Search back to beginning of paragraph
  58.     lineno = first_lineno - 1
  59.     line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
  60.     while lineno > 0 and not is_all_white(line):
  61.         lineno = lineno - 1
  62.         line = text.get("%d.0" % lineno, "%d.0 lineend" % lineno)
  63.     first = "%d.0" % (lineno+1)
  64.     return first, last, text.get(first, last)
  65.  
  66. def reformat_paragraph(data, limit=70):
  67.     lines = string.split(data, "\n")
  68.     i = 0
  69.     n = len(lines)
  70.     while i < n and is_all_white(lines[i]):
  71.         i = i+1
  72.     if i >= n:
  73.         return data
  74.     indent1 = get_indent(lines[i])
  75.     if i+1 < n and not is_all_white(lines[i+1]):
  76.         indent2 = get_indent(lines[i+1])
  77.     else:
  78.         indent2 = indent1
  79.     new = lines[:i]
  80.     partial = indent1
  81.     while i < n and not is_all_white(lines[i]):
  82.         # XXX Should take double space after period (etc.) into account
  83.         words = re.split("(\s+)", lines[i])
  84.         for j in range(0, len(words), 2):
  85.             word = words[j]
  86.             if not word:
  87.                 continue # Can happen when line ends in whitespace
  88.             if len(string.expandtabs(partial + word)) > limit and \
  89.                partial != indent1:
  90.                 new.append(string.rstrip(partial))
  91.                 partial = indent2
  92.             partial = partial + word + " "
  93.             if j+1 < len(words) and words[j+1] != " ":
  94.                 partial = partial + " "
  95.         i = i+1
  96.     new.append(string.rstrip(partial))
  97.     # XXX Should reformat remaining paragraphs as well
  98.     new.extend(lines[i:])
  99.     return string.join(new, "\n")
  100.  
  101. def is_all_white(line):
  102.     return re.match(r"^\s*$", line) is not None
  103.  
  104. def get_indent(line):
  105.     return re.match(r"^(\s*)", line).group()
  106.